#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mosquitto.h>
#include "z_logger.h"

static void log_mosq_error(const char *function, int rc) {
    if (MOSQ_ERR_ERRNO == rc) {
        log_error("%s=%d, %s", rc, strerror(rc));
    } else {
        log_error("%s=%d, %s", function, mosquitto_strerror(rc));
    }
}

static int _subscribe_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) {
    if (message->payloadlen >= 256) {
        log_warn("exec cmd is beyond limit length(0<%d<256)", message->payloadlen);
        return MOSQ_ERR_SUCCESS;
    }

    char *cmd = (char *) message->payload;
    cmd[message->payloadlen] = '\0';
    printf("exec bash: %s\n", cmd);
    FILE *out = popen(cmd, "r");

    char buf[4096];
    char *s = buf, *e = s + sizeof(buf);
    size_t n;
    while ((n = fread(s, 1, e - s, out)) > 0) {
        s += n;
    }

    pclose(out);

    if (s == buf) { //控制台没有输出
        strcpy(buf, "<exit>");
        s += 6;
    }

    return mosquitto_publish(mosq, NULL, "/user/bash/stdout", s - buf, buf, 0, false);
}

int main(int argc, char *argv[]) {
    int rc;

    log_init();
    rc = mosquitto_lib_init();
    if (MOSQ_ERR_SUCCESS != rc) {
        log_mosq_error("mosquitto_lib_init", rc);
        return EXIT_FAILURE;
    }

    rc = mosquitto_subscribe_callback(_subscribe_callback,
                                      NULL,
                                      "/user/bash/stdin",
                                      0,
                                      "127.0.0.1",
                                      1883,
                                      "mqtt_bash",
                                      60,
                                      false,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL);
    if (MOSQ_ERR_SUCCESS != rc) {
        log_mosq_error("mosquitto_subscribe_callback", rc);
        return EXIT_FAILURE;
    }

    rc = mosquitto_lib_cleanup();
    if (MOSQ_ERR_SUCCESS != rc) {
        log_mosq_error("mosquitto_lib_cleanup", rc);
        return EXIT_FAILURE;
    }
    log_fini();

    return EXIT_SUCCESS;
}